#include "Player.h"

static std::vector<float> play_data;
static unsigned int m_offset;
boost::signals2::signal<void(const std::vector<float> &)> m_signal;

// Two-channel sawtooth wave generator.
static int writeData(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
	double streamTime, RtAudioStreamStatus status, void *userData)
{
	Player *p = (Player *)userData;
	if (!p)
	{
		return 0;
	}
	unsigned int i;
	std::vector<float> data(nBufferFrames, 0);
	float *buffer = (float *)outputBuffer;
	if (status)
		std::cout << "Stream underflow detected!" << std::endl;
	// Write interleaved audio data.
	if (m_offset + nBufferFrames < play_data.size())
	{
		for (i = 0; i < nBufferFrames; i++)
		{
			
			data[i] = play_data[m_offset + i];
		}
		m_offset += nBufferFrames;
	}
	else if (m_offset + nBufferFrames == play_data.size())
	{
		for (i = 0; i < nBufferFrames; i++)
		{
			
			data[i] = play_data[m_offset + i];
		}
		m_offset = 0;
	}
	else
	{
		int tmp = play_data.size() - m_offset;
		for (i = 0; i < tmp; i++)
		{
			
			data[i] = play_data[m_offset + i];
		}
		m_offset = 0;
		for (i = tmp; i < nBufferFrames; i++)
		{
			
			data[i] = play_data[m_offset + i];
		}
		m_offset += nBufferFrames - tmp;
	}
	std::vector<float> out = p->filter(data);
	for (size_t i = 0; i < nBufferFrames; i++)
	{
		buffer[i] = out[i];
	}
	m_signal(out);
	return 0;
}


Player::Player()
{
	parameters.deviceId = dac.getDefaultOutputDevice();
	m_offset = 0;
	parameters.firstChannel = 0;
	m_Filter.SetFilterType(FILTERTYPE::FIR);
	m_Filter.SetWindowSize(255);
	m_Filter.SetPassType(PASSTYPE::HIGHPASS);
	m_Filter.SetFilterArg(1000, 5000, 48000);
}
Player::~Player()
{
}

bool Player::open(unsigned int channel, unsigned int sample_rate, unsigned int buffer_frames)
{
	parameters.nChannels = channel;
	if (dac.getDeviceCount() < 1) {
		std::cout << "\nNo audio devices found!\n";
		return false;
	}
	try {
		dac.openStream(&parameters, NULL, RTAUDIO_FLOAT32,
			sample_rate, &buffer_frames, writeData, this);
	}
	catch (RtAudioError& e) {
		e.printMessage();
		return false;
	}
	return true;
}

void Player::close()
{
	if (dac.isStreamOpen())
		dac.closeStream();
}

bool Player::play()
{
	try {
		dac.startStream();
	}
	catch (RtAudioError& e) {
		e.printMessage();
		return false;
	}
	m_offset = 0;
	return true;
}
bool Player::stop()
{
	try {
		// Stop the stream
		dac.stopStream();
	}
	catch (RtAudioError& e) {
		e.printMessage();
		return false;
	}
	return true;
}
void Player::setData(const std::vector<float> data)
{
	play_data.resize(data.size());
	std::copy(data.begin(), data.end(), play_data.begin());
}

void Player::setEqArgs(unsigned int count, unsigned int freq, int gain)
{
	m_eq.setEQArgs(count, freq, gain, 2.0, 48000);
}

std::vector<float> Player::filter(std::vector<float> &data)
{
	return m_Filter.FilterProcess(data);
	//return m_eq.run(data);
}

void Player::setFilterArg(FILTERTYPE f_Type, PASSTYPE p_Type, unsigned int WindowSize, unsigned int LowFreq, unsigned int HighFreq, unsigned int SampleRate)
{
	m_Filter.SetFilterType(f_Type);
	m_Filter.SetPassType(p_Type);
	m_Filter.SetWindowSize(WindowSize);
	m_Filter.SetFilterArg(LowFreq, HighFreq, SampleRate);	
}
